//promise的一些特点
// 1.promise是一个类，生成时会传递一个执行器（函数），执行器会立即执行
// 2.promise有三个状态，一经改变无法再改变  pending、fulfilled、rejected
// 3.reject,resolve是用来改变状态的 resolve->fulfilled,reject->rejected ,抛出成功值或者失败原因给接下来的then方法
// 4.then方法接受两个参数，分别是成功回调（参数成功值）和失败回调（参数失败原因）,返回的是一个新的promise对象
// 5.promise实例的then方法可多次调用


//then异步处理方案：then方法发现status为pending代表执行的是异步函数,可以先将两个回调函数存起来，状态改变时再调用

//then方法多次调用异步处理方案 ：将两个回调函数存成两个个回调栈，每次改变状态执行一次



const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise{
  status = PENDING  //promise的状态
  value = undefined //保存成功的值
  reason = undefined //保存失败的值
  successCallBack=[] //成功回调
  failCallBack=[]
  constructor(executor){
    try {
      executor(this.resolve, this.reject)
    } catch (e) {
      this.reject(e);
    }
  }
  resolve = value=>{
    if(this.status!==PENDING) return;
    this.status=FULFILLED
    this.value = value
    // this.successCallBack&&this.successCallBack(this.value)
    while(this.successCallBack.length>0){
      this.successCallBack.shift()()
    }
  }
  reject = reason=>{
    if(this.status!==PENDING) return;
    this.status=REJECTED
    this.reason=reason
    // this.failCallBack&&this.failCallBack(this.reason)
    while(this.failCallBack.length>0){
      this.failCallBack.shift()()
    }
  }
  then(successCallBack,failCallBack){
    // 参数可选
    successCallBack = successCallBack ? successCallBack : value => value;
    // 参数可选
    failCallBack = failCallBack ? failCallBack: reason => { throw reason };
    let promise2 = new MyPromise((resolve,reject)=>{
      if(this.status===FULFILLED){
        setTimeout(() => {
          try {
            let x = successCallBack(this.value)
            // 1.判断x是不是promise
            // 2.普通值直接resolve
            // 3.promise对象先看返回结果是不是成功还是失败分别调用promise对象的resolve和reject方法
            resolvePromise(promise2,x,resolve,reject)  
          } catch (error) {
            reject(error)
          }
        }, 0);
      }else if(this.status===REJECTED){
        setTimeout(() => {
          try {
            let x = failCallBack(this.reason)
            // 1.判断x是不是promise
            // 2.普通值直接resolve
            // 3.promise对象先看返回结果是不是成功还是失败分别调用promise对象的resolve和reject方法
            resolvePromise(promise2,x,resolve,reject)  
          } catch (error) {
            reject(error)
          }
        }, 0);
      }else{
        //代表遇到的是异步函数
        /* 这种处理方式在then多次调用且执行器改变状态是异步时，会导致只有最后一个生效
        this.successCallBack=successCallBack
        this.failCallBack=failCallBack
        */
        //  this.successCallBack.push(successCallBack)  无法处理返回为promise情况
        //  this.failCallBack.push(failCallBack)
        this.successCallBack.push(()=>{
          setTimeout(() => {
            try {
              let x = successCallBack(this.value)
              // 1.判断x是不是promise
              // 2.普通值直接resolve
              // 3.promise对象先看返回结果是不是成功还是失败分别调用promise对象的resolve和reject方法
              resolvePromise(promise2,x,resolve,reject)  
            } catch (error) {
              reject(error)
            }
          }, 0);
        })
        this.failCallBack.push(()=>{
          setTimeout(() => {
            try {
              let x = failCallBack(this.reason)
              // 1.判断x是不是promise
              // 2.普通值直接resolve
              // 3.promise对象先看返回结果是不是成功还是失败分别调用promise对象的resolve和reject方法
              resolvePromise(promise2,x,resolve,reject)  
            } catch (error) {
              reject(error)
            }
          }, 0);
        })
      }
    })
    return promise2
  }
  finally (callback) {
    return this.then(value => {
      return MyPromise.resolve(callback()).then(() => value);
    }, reason => {
      return MyPromise.resolve(callback()).then(() => { throw reason })
    })
  }
  catch (failCallBack) {
    return this.then(undefined, failCallBack)
  }
  static resolve (value) {
    if (value instanceof MyPromise) return value;
    return new MyPromise(resolve => resolve(value));
  }
  static all (array) {
    let result = []
    let index = 0
    return new MyPromise((resolve,reject)=>{
      function addData(key,value){
        result[key]=value
        index++
        if(index === array.length){
          resolve(result)
        }
      }
      for (let i = 0; i < array.length; i++) {
        const element = array[i];
        if(element instanceof MyPromise){
          element.then(value=>addData(i,value),reason=>reject(reason))
        }else{
          addData(i,element)
        }
      }
    })
  }
}

function resolvePromise(promise2,x,resolve,reject){
  // console.log(x)
  //判断返回的promise是不是自身
  if(promise2===x){
    return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
  }
  if(x instanceof MyPromise){
    x.then(resolve,reject) //如果是promise对象调用他的then方法，传递resolve方法成功执行，reject方法失败执行
  }else{
    resolve(x)
  }
}
module.exports = MyPromise